.TITLE TTRW .IDENT /10.00/ ; ; ; Copyright (c) 1995-1999 by Mentec, Inc., U.S.A. ; All rights reserved ; ; ; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED ; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE. ; ; ; 25-JAN-78 PETER WANNHEDEN ; ; PREVIOUSLY MODIFIED BY: ; ; P. WANNHEDEN ; D. R. DONCHIN ; T. LEKAS ; S. C. ADAMS ; R. S. PHILPOTT ; M. W. ZAHAREE ; ; ; MODIFIED FOR RSX-11M-PLUS V4.3 BY: ; ; M. W. ZAHAREE 28-JUN-89 10.00 ; MWZ010 -- DON'T CLOBBER OTHER BITS WHEN INITIALIZING U.AFLG FOR ACD ; CALLS. ;+ ; ****** T T R W ****** ; ; THIS MODULE CONTAINS THE ROUTINES TO STARTUP AND COMPLETE A READ OR ; WRITE REQUEST THAT HAS BEEN DEQUEUED FOR A TERMINAL. BOTH TYPES OF REQUESTS ; HAVE THREE PARTS. THE FIRST STEP DOES PRE-PROCESSING OF THE PARAMETERS ; CONTAINED IN THE I/O PACKET NECESSARY TO PROCEED TO THE SECOND STEP. THE ; SECOND STEP SETS UP BUFFER POINTERS, ETC. FOR THE NEXT PART OF THE DATA ; TRANSFER. THIS STEP IS REPEATED UNTIL THE TRANSFER FULLY COMPLETES. THE ; FINAL STEP CLEANS UP AND PASSES THE I/O REQUEST BACK TO THE SYSTEM WITH A ; COMPLETION STATUS. NOTE THAT BOTH SOLICITED AND UNSOLICITED INPUT ARE ; HANDLED BY THE INPUT ROUTINES. ;- ; .SBTTL .MCALLS AND SYMBOL DEFINITIONS .MCALL TTSYM$ TTSYM$ ;DEFINE TF.XXX SYMBOLS .IF DF T$$SPC!T$$CCA!T$$EIO .MCALL PKTDF$ PKTDF$ ;DEFINE CLI COMMAND BUFFER HEADER OFFSETS ;AND ACB OFFSETS AND IOPX OFFSETS .ENDC ;T$$SPC!T$$CCA!T$$EIO .PSECT MAP5.6 .PAGE .SBTTL PPEIO - EXTENDED READ/WRITE PRE-PROCESSING ; ;+ ; **-PPEIO - PRE-PROCESSING FOR EXTENDED READ AND WRITE (IO.EIO) ; ; THIS ROUTINE DOES THE SETUP NECESSARY TO START UP AN EXTENDED READ OR ; WRITE REQUEST. THE FOLLOWING STEPS ARE TAKEN: ; 1. LOCATE THE I/O PACKET EXTENSION (IOPX) ASSOCIATED WITH THE ; IO.EIO REQUEST'S I/O PACKET. THE IOPX IS REMOVED FROM ; THE IOPX LIST. ; 2. MOVE THE I/O FUNCTION MODIFIERS FROM THE IOPX TO THE FUNCTION ; CODE FIELD IN THE CURRENT I/O PACKET. THE FUNCTION CODE ; IS FLAGGED AS AN IO.EIO REQUEST BY SETTING THE HIGH BIT. ; 3. ALL PARAMETERS THAT WERE EARLIER SAVED IN THE IOPX ARE NOW ; TRANSFERRED TO THE I/O PACKET FOR THE IO.EIO REQUEST. ; 4. THE IOPX IS DEALLOCATED. ; 5. DISPATCH TO THE ROUTINE FOR HANDLING THE SPECIFIC TYPE OF ; I/O REQUEST. ; ; *** NOTE *** AT PRESENT, THIS ROUTINE ASSUMES THAT THE ONLY REQUEST THAT ; WILL GET PASSED TO IT IS AN EXTENDED READ REQUEST (IO.EIO!TF.RLB). ; ANY IO.EIO!TF.WLB OPERATION IS EXPECTED TO HAVE BEEN MAPPED INTO A ; NORMAL IO.WLB REQUEST PRIOR TO BEING QUEUED (WITH NO IOPX). ; ; INPUTS: ; R3 => CURRENT I/O REQUEST PACKET ; R4 => UCBX FOR THE TERMINAL ; R5 => U.TSTA OF THE TERMINAL UCB ; U.TRTT(R4) => TERMINATOR TABLE FOR THE READ, IF ANY (SET UP BY FPGRQ). ; I.LNK(R3) = 0 ; ; OUTPUTS: ; IOPX IS DEALLOCATED ; CURRENT I/O PACKET IS SET UP FOR PROCESSING BY "PPRLB" OR "PPRPR1". ; ; REGISTERS MODIFIED: R0, R1, R2 ;- ; .IF DF T$$EIO ASSUME I.XLNK,0 ASSUME I.XLNK+2,I.XIOP ASSUME I.XIOP+2,I.XTCB ASSUME I.XTCB+2,I.XMOD ASSUME I.XMOD+4,I.XRBF ASSUME I.XRBF+4,I.XRBL ASSUME I.XRBL+2,I.XTMO ASSUME I.XTMO+2,I.XPBF ASSUME I.XPBF+4,I.XPBL ASSUME I.XPBL+2,I.XPBV PPEIO:: MOV R5,R0 ;GET COPY OF UCB POINTER ADD #U.TIXL-U.TSTA,R0 ;MAKE POINTER TO U.TIXL (IOPX LISTHEAD) 10$: MOV R0,R1 ;MAKE THIS THE PREVIOUS IOPX POINTER MOV (R1),R0 ;LOCATE THE NEXT IOPX (MUST BE HERE SOMEWHERE) CMP I.XIOP(R0),R3 ;DOES THIS IOPX BELONG TO THE CURRENT REQUEST? BNE 10$ ;IF NE, NO...LOOP TILL WE FIND IT MOV (R0),(R1) ;REMOVE THIS IOPX FROM THE WAIT LIST ADD #I.XMOD,R0 ;POINT PAST LINK, I/O PACKET AND TCB OFFSETS MOV (R0)+,I.FCN(R3) ;STORE REQUESTED MODIFIERS IN I/O PACKET TST (R0)+ ;SKIP OVER UNUSED MODIFIER WORD BIS #S6.EIO,U.TST6-U.TSTA(R5) ;INDICATE REQUEST IS (WAS) AN IO.EIO MOV R3,R1 ;COPY I/O PACKET ADDRESS ADD #I.PRM,R1 ;MAKE A POINTER INTO THE PARAMETER LIST MOV (R0)+,(R1)+ ;COPY 1.ST ADDRESS DOUBLE WORD OF DATA BUFFER MOV (R0)+,(R1)+ ;COPY 2.ND ADDRESS DOUBLE WORD OF DATA BUFFER MOV (R0)+,(R1)+ ;COPY DATA BUFFER LENGTH MOV (R0)+,(R1)+ ;COPY TIMEOUT FOR THE READ 20$: MOV (R0)+,(R1)+ ;COPY 1.ST ADDRESS DOUBLE WORD OF PROMPT BUFFER MOV (R0)+,(R1)+ ;COPY 2.ND ADDRESS DOUBLE WORD OF PROMPT BUFFER MOV (R0)+,(R1)+ ;COPY PROMPT BUFFER LENGTH MOV (R0),(R1) ;COPY PROMPT VFC SUB #I.XPBV,R0 ;POINT BACK TO START OF IOPX MOV R3,-(SP) ;SAVE R3 MOV #I.XLEN,R1 ;GET SIZE OF IOPX CALL $DEACB ;DEALLOCATE IOPX MOV (SP)+,R3 ;RESTORE R3 .IF DF T$$RPR BIT #TF.RPR,I.FCN(R3) ;DID USER REQUEST A READ W/PROMPT? BEQ PPRLB1 ;IF EQ, NO...PROCESS AS A NORMAL READ JMP PPRPR1 ;GO PROCESS THE PROMPT PART AS AN OUTPUT .IFF ;T$$RPR .IF DF B$$MAP BR PPRLB1 ;PROCESS AS A NORMAL READ REQUEST .ENDC ;B$$MAP .ENDC ;T$$RPR .ENDC ;T$$EIO .PAGE .SBTTL INPUT REQUEST PRE-PROCESSING .SBTTL . PPRSD - READ-SPECIAL-DATA REQUEST (IO.RSD) ; ;+ ; **-PPRSD - PRE-PROCESSING FOR READ-SPECIAL-DATA (IO.RSD) ; **-PPRLB - PRE-PROCESSING FOR READ-LOGICAL-BLOCK (IO.RLB) ; ; THIS ROUTINE DOES THE SETUP NECESSARY TO START UP AN IO.RSD OR IO.RLB ; REQUEST. ANY OF THE FOLLOWING STEPS MAY BE TAKEN: ; 1. FOR ENTRY AT "PPRSD", THE HIGH BYTE OF THE FUNCTION CODE IS ; CLEARED, SINCE IT MAY BE NECESSARY TO STORE OTHER READ ; MODIFIERS FOR LATER CHECKING. ; 2. FOR ENTRY AT "PPRLB", THE UNSOLICITED INPUT AST CONTROL BLOCK IS ; UNLOCKED IN CASE IT IS LOCKED DUE TO A NOTIFICATION AST ; HAVING BEEN SENT (TF.NOT MODIFIER ON THE ATTACH REQUEST). ; 3. THE I/O REQUEST PACKET BECOMES THE CURRENT REQUEST PACKET. ; 4. THE MODIFIERS FROM THE READ REQUEST ARE COMBINED WITH CERTAIN ; TERMINAL CHARACTERISTICS TO DEFINE WHAT THE MODIFIERS FOR ; THE CURRENT READ WILL BE. FOR EXAMPLE, IF THE TERMINAL IS ; SET TO "NOECHO" MODE, THE READ MODIFIER TF.RNE WILL BE SET ; REGARDLESS OF WHETHER THE USER SPECIFIED IT IN THE QIO. ; THE RESULTING MODIFIERS ARE SAVED IN THE I/O PACKET. ; 5. THE TIMEOUT REQUEST MODIFIER/VALUE IS PROCESSED. ; 6. THE APPROPRIATE STATUS BITS ARE ESTABLISHED TO MARK INPUT ; BUSY AND INITIALIZE INPUT PROCESSING. ; 7. A REQUEST FOR "LEADING LINEFEED" IS MADE IF NECESSARY. ; 8. CONTROL IS PASSED TO THE ROUTINES TO START BUFFERED OR UNBUFFERED ; INPUT, WHICHEVER IS NECESSARY. ; ; INPUTS: ; R3 => CURRENT I/O REQUEST PACKET ; R4 => UCBX FOR THE TERMINAL ; R5 => U.TSTA OF THE TERMINAL UCB ; I.LNK(R3) = 0 IF THE REQUEST IS IO.RLB OR IO.RSD ; = 1 IF THIS IS THE READ PART OF A READ AFTER PROMPT REQUEST ; (THE PROMPT OUTPUT HAS BEEN COMPLETED) ; OUTPUTS: ; R2 => FIRST INPUT BUFFER (IF BUFFERED INPUT IS TO BE STARTED) ; (R4) => CURRENT I/O REQUEST PACKET ; UCB STATUS AND UCBX INITIALIZED TO START INPUT ; ; REGISTERS MODIFIED: R0, R1, R2 ;- ; .IF DF B$$MAP PPRSD:: CLRB I.FCN+1(R3) ;CLEAR OUT HIGH BYTE OF THE FUNCTION CODE BR RLB1 ;CONTINUE IN COMMON CODE .ENDC ;B$$MAP .SBTTL . PPRLB - READ-LOGICAL-BLOCK REQUEST (IO.RLB) PPRLB:: .IF DF T$$EIO BIC #S6.EIO,U.TST6-U.TSTA(R5) ;INDICATE THAT THIS IS NOT EXTENDED IO .ENDC ;T$$EIO CLRB I.FCN+1(R3) ;CLEAR FLAGS IN HIGH BYTE PPRLB1: .IF DF T$$CCA MOV U.TAST(R4),R0 ;GET UNSOLICITED INPUT AST BLOCK IF THERE IS ONE BEQ RLB1 ;IF EQ, NOT ONE...SKIP BICB #AF.LCK,A.PRM+5(R0) ;UNLOCK THE AST BLOCK IN CASE IT WAS... ; ...LOCKED DUE TO TF.NOT .ENDC ;T$$CCA RLB1: BIC #S5.ITI,U.TST5-U.TSTA(R5) ;INDICATE THAT THIS IS NOT ;IMMEDIATE TIMEOUT ASSUME U.TCI,0 MOV R3,(R4)+ ;SAVE THE CURRENT PACKET ADDRESS ; ; SET UP THE FULL READ MODIFIERS FOR THE CURRENT READ REQUEST. THIS INVOLVES ; TAKING THE MODIFIERS SPECIFIED WITH THE READ AND "OR'ING" THEM WITH THE ; PERMANENT CHARACTERISTICS FLAGS. NOTE THAT THE MODIFIERS MAY EXTEND INTO ; THE HIGH BYTE OF I.FCN IF CONTROL WAS PASSED HERE FROM "PPEIO". ; NOTE: IF THERE IS EVER A READ MODIFIER WITH THE SAME BIT VALUE AS S1.TSY ; AND S3.TSY, THIS HERE ROB PHILPOTT MEMORIAL BIT SETTING CODE WILL BREAK! ; ASSUME TF.RAL,S3.RAL ASSUME TF.RNE,S3.NEC ASSUME TF.RPT,S3.PTH ASSUME TF.RES,S3.RES MOV I.FCN(R3),R0 ;GET ALL READ MODIFIERS (COULD BE FROM PPEIO) BIC #4,R0 ;CLEAR MODIFIERS THAT WON'T MAP MOV 4(R5),R1 ;GET THE CURRENT INPUT CHARACTERISTICS BITS BIC #^C,R1 ;CLEAN THEM UP BIS R1,R0 ;"OR" IN PERM CHARACTERISTICS WITH TEMP FLAGS MOV R0,I.FCN(R3) ;SAVE THE COMPLETE FLAGS IN THE I/O PACKET ; ; SET UP RST AND RSP ; BIT #TF.RST, R0 ;DOING OLD-STYLE READ W/ SPEC. TERM? BEQ 5$ ;BR IF NO BIS #S1.RSP!S1.RNF!S1.TNE,R0 ;FORCE SPEC PROC AND NO FILTER 5$: BIT #TF.RTT,R0 ;NEW-STYLE READ WITH TERM. TABLE? BEQ 10$ ;BR IF NO BIS #S1.RST,R0 ;SAY WE'RE USING SPECIAL TERMINATORS 10$: .IF DF T$$EIO MOV R0,R1 ;GET FUNCTION CODE ASSUME TF.RDI,S6.RDI ASSUME TF.RLU,S6.RLU BIC #^C,R1 ;ISOLATE RDI AND RLU BITS BIS R1,U.TST6-U.TSTA(R5) ;AND PLOP THEM INTO STATUS WORD .ENDC ;T$$EIO ; ; SET UP TTSYNC AND PASTHRU AS FOLLOWS: ; 1. OLD STYLE "TF.RAL" AND "SET /RPA (S3.RAL)" MAP INTO PASTHRU MODE ; WITH TTSYNC DISABLED. ; 2. NEW STYLE "TF.RPT" AND "PASTHRU MODE" ARE INDEPENDENT OF TTSYNC. ; 3. IF TTSYNC IS DISABLED, TF.RPT IS EQUIVALENT TO OLD "TF.RAL". ; ASSUME S3.RAL,S1.PTH ASSUME S3.TSY,S1.TSY BIT #TF.RAL,R0 ;WAS EITHER TF.RAL OR S3.RAL SET? BEQ 20$ ;IF EQ, NO...SKIP TO CHECK FOR PASTHRU MODE BIC #S1.TSY,(R5) ;CLEAR TTSYNC FOR OLD READ-PASS-ALL MODE BIC #S1.TSY,R0 ;CLEAR TTSYNC FOR OLD READ-PASS-ALL MODE BR 30$ ;SKIP TO FORCE PASTHRU MODE ON THE READ ALSO 20$: BIT #TF.RPT,R0 ;WAS EITHER TF.RPT OR S3.PTH SET? BEQ 40$ ;IF EQ, NO...SKIP TO FINISH MODIFIER PROCESSING 30$: BIS #S1.PTH,R0 ;BOTH TF.RPT AND TF.RAL USE PASSTHRU MODE ; ; ESTABLISH THE TIMEOUT VALUE TO BE USED FOR THIS READ REQUEST. NOTE THAT ; NORMAL READS MULTIPLY THE TIMEOUT VALUE BY TEN. "IO.EIO" TAKE THE TIMEOUT ; VALUE AS SPECIFIED. A ZERO TIMEOUT ON A NORMAL READ WILL TIME OUT WHICH ; IS A CHANGE FROM THE OLD BEHAVIOR. A ZERO TIMEOUT TIMES OUT IMMEDIATELY, ; RETURNING DATA THAT IS CURRENTLY IN THE TYPE-AHEAD BUFFER (IF ANY). ; 40$: CLR R1 ;ASSUME ZERO-LENGTH TIMEOUT SPECIFIED ASSUME TF.TMO,200 TSTB R0 ;IS USER REQUESTING A TIMEOUT ON THE READ? BPL 70$ ;IF PL, NO...SKIP TIMEOUT CHECKS MOVB I.PRM+6(R3),R1 ;GET USER SPECIFIED TIMEOUT VALUE BNE 45$ ;IF NE, NOT ZERO TIMEOUT BIS #S5.ITI,U.TST5-U.TSTA(R5) ;INDICATE IMMEDIATE TIMEOUT IS NEEDED BR 70$ ;AND VALUE IS READY TO STASH 45$: .IF DF T$$EIO BIT #S6.EIO,U.TST6-U.TSTA(R5) ;WAS/IS THIS AN EXTENDED IO? BNE 70$ ;IF SO, INTERPRET VALUE DIRECTLY .ENDC ;T$$EIO ; ; MULTIPLY THE SPECIFIED TIMEOUT VALUE BY TEN FOR NORMAL READS. ; CMPB R1,#<377/10.> ;EXCEED MAXIMUM TIMEOUT VALUE? BLOS 50$ ;IF LOS, NO MOV #377,R1 ;SET MAXIMUM TIMEOUT LENGTH IN SECONDS BR 70$ ;USE THIS TIMEOUT VALUE 50$: .IF DF R$$EIS MUL #10.,R1 ;ADJUST TO UNITS OF TEN .IFF ;R$$EIS ASL R1 ;MULTIPLY BY TWO MOV R1,-(SP) ;SAVE PARTIAL RESULT ASL R1 ;MAKE IT X 4 ASL R1 ;MAKE IT X 8 ADD (SP)+,R1 ;(X 8) + (X 2) = (X 10) .ENDC ;R$$EIS 70$: MOVB R1,U.TITI-U.TIP(R4) ;SAVE TIMEOUT VALUE MOVB R1,I.PRM+6(R3) ;SAVE TIMEOUT VALUE IN I/O PACKET FOR LATER ; ; TURN NECESSARY MODIFIERS INTO INPUT STATUS FLAGS IN U.TSTA. ; ASSUME TF.RST,S1.RST ASSUME S3.NEC,S1.RNE ASSUME S3.RES,S1.RES ASSUME TF.RNF,S1.RNF ASSUME TF.TNE,S1.TNE BIC #^C,R0 ;CLEAR UNDESIRED STATUS BITS FROM READ MODIFIERS BIS R0,(R5) ;ESTABLISH NEW INPUT PROCESSING FLAGS BIC #S2.CTO,2(R5) ;READ CLEARS ^O STATE MOVB #TF.RLB,I.FCN+1(R3) ;REMEMBER THAT THIS WAS A READ ; ; DETERMINE WHETHER OR NOT TO OUTPUT A LEADING LINEFEED. ; BIT #S1.RNE,(R5)+ ;IS INPUT ECHOING REQUIRED? BNE 80$ ;IF NE, NO...SKIP ASSUME S3.FDX,200 TSTB 2(R5) ;IS THE LINE SET TO FULL DUPLEX MODE? BMI 80$ ;IF MI, NO...SKIP LEADING LINEFEED BIT #S2.FLF,(R5) ;NEED TO FORCE A LINEFEED? BEQ 80$ ;IF EQ, NO...DON'T OUTPUT ONE - SKIP MOV #PRLF,-(SP) ;OUTPUT LEADING LF WHEN WE EXIT THIS ROUTINE 80$: .IF DF T$$EIO BIS #S1.IBY,-(R5) ;SET INPUT BUSY ASSUME S6.RDI,100000 TST U.TST6-U.TSTA(R5) ;DEFAULT INPUT SPECIFIED? BMI 90$ ;IF NE YES, BUFFER STATUS HAS ALREADY BEEN SET BIS #S1.IBF,@R5 ;ASSUME BUFFERED INPUT .IFF ;T$$EIO BIS #S1.IBY!S1.IBF,-(R5) ;SET INPUT BUSY AND ASSUME BUFFERED INPUT .ENDC ;T$$EIO 90$: MOVB U.TCHP-U.TSTA(R5),U.TIHP-2(R4) ;SAVE INITIAL CURSOR POSITION .IF DF T$$RPR TST (R3) ;HAVE WE JUST FINISHED OUTPUTTING A PROMPT? BEQ RDBCHK ;IF EQ, NO...SKIP CLR (R3) ;RESET THE COMPLETION STATUS FIELD TST I.PRM+16(R3) ;DID THE PROMPT SUCCESSFULLY INITIALIZE... ; ...INTERMEDIATE BUFFERING? BEQ UNBI ;IF EQ, NO...GO AND DO UNBUFFERED READ MOV U.TFIB-U.TIP(R4),R2 ;ELSE, GET THE FIRST INPUT BUFFER... ; ...WHICH WAS ALLOCATED BEFORE PROMPTING BR BUFRD ;DO BUFFERED READ .ENDC ;T$$RPR .PAGE .SBTTL INPUT REQUEST BUFFER HANDLING .SBTTL . RDBCHK - DETERMINE NEED FOR BUFFERED/UNBUFFERED INPUT ; ; RDBCHK - DETERMINE THE TYPE OF INPUT BUFFERING TO BE USED ON THIS READ. ; RDBCHK: CALL $TSTBF ;SHOULD WE DO A BUFFERED READ? BCS UNBI ;IF CS, NO...DO AN UNBUFFERED ONE .IF DF T$$EIO ASSUME S6.RDI,100000 TST U.TST6-U.TSTA(R5) ;READING WITH DEFAULT INPUT? BPL 10$ ;IF EQ NO, NEED TO ALLOCATE A BUFFER MOV U.TDIF-U.TIP(R4),R2 ;USE DEFAULT INPUT BUFFERS FOR INPUT DATA BNE 20$ ;IF NE HAVE A BUFFER WE CAN USE BR UNBI ;ELSE NOT ENOUGH BUFFERS AVAILABLE .ENDC ;T$$EIO 10$: CALL ALTB ;GET A BUFFER FOR THE BUFFERED READ BCS UNBI ;IF CS, FAILED...MUST DO UNBUFFERED READ 20$: MOV R2,-(SP) ;SAVE THE BUFFER ADDRESS CALL $INIBF ;INITIALIZE INTERMEDIATE BUFFERING MOV (SP)+,R2 ;RETRIEVE THE BUFFER ADDRESS .DSABL LSB .SBTTL . BUFRD - SET UP TO DO BUFFERED INPUT ; ; BUFRD - SET UP FOR BUFFERED INPUT. ; BUFRD: ADD #U.TTIC-U.TIP,R4 ;POINT TO U.TTIC MOV R4,R1 ;COPY POINTER MOV I.PRM+4(R3),(R1)+ ;SET UP MAXIMUM BYTE COUNT ASSUME U.TFIB,U.TTIC+2 ; ; BUFRD1 - LINK CURRENT BUFFER TO PREVIOUS ONE ; BUFRD1: MOV R2,(R1) ;LINK FIRST BUFFER TO U.TFIB .SBTTL . NXTIB - GET NEXT INPUT BUFFER ; ;+ ; **-NXTIB - GET NEXT INPUT BUFFER ; ; *** NOTE *** THIS ROUTINE IS ALSO CALLED AT DEVICE PRIORITY FROM THE ; INPUT DONE INTERRUPT SERVICE ROUTINE. ; ; INPUTS: ; R2 => NEW INPUT BUFFER ; R4 => U.TTIC OF THE TERMINAL UCBX ; U.TTIC = TOTAL REMAINING BYTE COUNT ; ; OUTPUTS: ; R4 => U.TIC OF THE TERMINAL UCBX ; NEW BUFFER LINKED TO OLD BUFFER ; SECOND WORD OF NEW BUFFER SET UP WITH LOGICAL BUFFER LENGTH ; U.TIP, U.TIP+2, U.TIC, AND U.TTIC ARE UPDATED ; CC-Z = 0 IF THE INPUT BYTE COUNT IS NOT YET EXHAUSTED ; = 1 OTHERWISE ; ; REGISTERS MODIFIED: R2, R3, R4 ;- ; NXTIB:: TST (R2)+ ;POINT TO SECOND WORD OF THE NEW BUFFER MOV #T$$BFL-4,(R2) ;SET LOGICAL LENGTH OF THE BUFFER SUB (R2),(R4) ;ADJUST U.TTIC APPROPRIATELY BPL 10$ ;IF PL, THERE IS MORE ROOM STILL...SKIP ADD (R4),(R2) ;WENT BELOW ZERO - ADJUST LOG. BUFFER LENGTH CLR (R4) ;U.TTIC <-- 0 ASSUME U.TIP,U.TTIC-6 10$: CMP -(R4),-(R4) ;POINT TO U.TIP+2 CMP -(R4),-(R2) ;POINT R4 TO U.TIP AND R2 TO START OF THE BUFFER .PAGE .SBTTL GENERAL INPUT/OUTPUT BUFFER HANDLING .SBTTL . UPUB - UPDATE UCBX PARAMETERS FOR BUFFERED I/O ; ;+ ; **-UPUB - UPDATE PARAMETERS IN UCBX FOR BUFFERED INPUT OR OUTPUT. ; ; THIS ROUTINE IS CALLED IN THREE SITUATIONS: ; 1. AT PRIORITY 0 TO START INPUT ; 2. AT DEVICE PRIORITY TO START OUTPUT ; 3. AT DEVICE PRIORITY FROM THE OUTPUT OR INPUT INTERRUPT SERVICE ; ROUTINE TO SWITCH FROM THE CURRENT PARTIAL BUFFER TO THE NEXT. ; ; INPUTS: ; R2 => INPUT OR OUTPUT BUFFER ; R4 => U.TIP (INPUT) OR U.TOP (OUTPUT) OF THE TERMINAL'S UCBX ; 2(R2) = LOGICAL BUFFER LENGTH ; ; OUTPUTS: ; R2 => SECOND WORD OF BUFFER ; R4 => U.TIC/U.TOC OF THE TERMINAL UCBX ; U.TIP, U.TIP+2, U.TIC (OR U.TOP, U.TOP+2, U.TOC) ARE UPDATED FOR NEXT ; PARTIAL TRANSFER. ; CC-Z = 0 IF THERE IS MORE WORK TO DO ; = 1 OTHERWISE ; ; REGISTERS MODIFIED: R2, R4 ;- ; UPUB:: MOV R2,(R4)+ ;U.TIP+0/U.TOP+0 <-- BUFFER ADDRESS CMP (R2)+,(R2)+ ;SKIP OVER LINK AND LENGTH WORDS MOV R2,(R4)+ ;U.TIP+2/U.TOP+2 <-- START OF DATA IN BUFFER MOV -(R2),(R4) ;U.TIC/U.TOC <-- BYTE COUNT FOR THIS ;(POSSIBLY PARTIAL) TRANSFER RETURN .SBTTL . UNBI - ESTABLISH NON-BUFFERED INPUT ; ; UNBI - DO NON-BUFFERED INPUT. ; UNBI: CLR I.PRM+16(R3) ;USE $IOFIN AT END BIC #S1.IBF,(R5) ;SHOW UNBUFFERED INPUT ASSUME U.TIP, .SBTTL . UPUNB - UPDATE UCB FOR NON-BUFFERED INPUT ; ;+ ; **-UPUNB - UPDATE UCB FOR NON-BUFFERED INPUT. ; ; INPUTS: ; R3 => CURRENT I/O REQUEST PACKET ; R4 => U.TIP OF THE TERMINAL UCBX ; ; OUTPUTS: ; R4 => U.TTIC OF THE TERMINAL UCBX ; U.TIP, U.TIP+2, U.TIC, U.TTIC UPDATED FOR NON-BUFFERED INPUT ; ; REGISTERS MODIFIED: R3, R4 ;- ; UPUNB:: ADD #I.PRM,R3 ;POINT TO PARAMETERS IN PACKET MOV (R3)+,(R4)+ ;U.TIP+0 <-- BUFFER ADDRESS (ADRS DOUBLE WORD) MOV (R3)+,(R4)+ ;U.TIP+2 <-- 2.ND HALF OF ADDRESS DOUBLE WORD ASSUME U.TIC, MOV (R3)+,(R4)+ ;U.TIC <-- BYTE COUNT ASSUME U.TTIC, CLR (R4) ;U.TTIC <-- 0 RETURN ;ALL DONE .PAGE .SBTTL INPUT REQUEST COMPLETION .SBTTL . FPIRD - INPUT REQUEST DONE FORK PROCESS ; ;+ ; **-FPIRD - INPUT REQUEST DONE FORK PROCESS. ; ; THIS ROUTINE IS ENTERED FROM THE FORK DISPATCHER WHEN: ; 1. AN END OF LINE WAS DETECTED (OR A HARD RECEIVE ERROR) ; 2. AN INTERMEDIATE BUFFER IS FULL ; 3. THE USER TASK BUFFER IS FULL (NON-BUFFERED SOLICITED INPUT) ; ; AFTER INITIALIZING, THIS ROUTINE DISPATCHES TO PROCESS COMPLETION OF ; EITHER SOLICITED OR UNSOLICITED INPUT. ; ; INPUTS: ; R4 => UCBX OF THE TERMINAL ; R5 => U.TSTA OF THE TERMINAL UCB ; ; OUTPUTS: NONE. ; ; REGISTERS MODIFIED: R0, R1, R2, R3 ;- ; FPIRD:: ASSUME U.TCI,0 MOV (R4)+,R3 ;GET CURRENT REQUEST PACKET ASSUME U.TIP,U.TCI+2 MOV (R4)+,R1 ;GET CURRENT BUFFER (IF BUFFERED INPUT) ASSUME U.TIC,U.TIP+4 TST (R4)+ ;POINT TO U.TIC ASSUME U.TTIC,U.TIC+2 ADD (R4)+,(R4) ;ADD U.TIC TO U.TTIC TO GET TOTAL... ; ...REMAINING BYTES TO READ BEQ IRQDON ;IF EQ, THE BUFFER IS FULL...COMPLETE THE READ TST (R3) ;HAS A COMPLETION STATUS BEEN SET? BNE IRQDON ;IF NE, YES...COMPLETE THE READ ; ; HERE WE ARE DOING BUFFERED INPUT AND THE CURRENT BUFFER IS FULL. WE WILL ; TRY TO ALLOCATE ANOTHER BUFFER AND CONTINUE THE READ. NOTE THAT THE INPUT ; ISR HAS ALREADY CHECKED WHETHER THERE IS ANOTHER BUFFER ALLOCATED (THIS ; COULD BE THE CASE IF THE OPERATOR DID RUBOUT OR CTRL-U). IF THERE IS ; ANOTHER BUFFER ALLOCATED ALREADY, WE DON'T COME HERE. ; CALL ALTB ;GET ANOTHER INPUT BUFFER BCC BUFRD1 ;IF CC, LINK TO PREVIOUS BUFFER AND CONTINUE MOV #IE.NOD,(R3) ;SET AN ERROR STATUS ASSUME S1.USI,100000 TST (R5) ;ARE WE DOING UNSOLICITED INPUT? BPL IRQDON ;IF PL, NO...SKIP ; ; UNSOLICITED INPUT REQUIRES ANOTHER BUFFER, WHICH WE FAILED TO ; ALLOCATE. THE STATUS "IE.NOD" WILL FORCE A ^U TO FLUSH THE INPUT. ; JMP USIDON ;COMPLETE UNSOLICITED INPUT ; ; SOLICITED INPUT REQUIRES ANOTHER BUFFER, WHICH WE FAILED TO ALLOCATE. ; WE WILL RETURN PARTIAL INPUT WITH THE STATUS "IE.NOD". ; .PAGE .SBTTL . IRQDON - AN INPUT REQUEST HAS COMPLETED ; ; IRQDON - INPUT REQUEST COMPLETED ; IRQDON: .IF DF T$$ACD MOV U.ACB-U.TSTA(R5),R2 ;GET ACB BEQ 30$ ;TERMINAL DOESN'T HAVE ONE - JUMP BIC #UA.TRA,U.AFLG-U.TSTA(R5);SET DEFAULT PROCESSING MOV (R3),A.IOS(R2) ;SET INPUT COMPLETION STATUS MOV #A.INPU,R0 ;SET INPUT COMPLETION ENTRY POINT CALL $SWACD ;CALL ACD MOV A.IOS(R2),(R3) ;SET POSSIBLY DIFFERENT INPUT STATUS CODE BIT #UA.TRA,U.AFLG-U.TSTA(R5) ;TRANSFER CHARACTERS NOW? BEQ 30$ ;IF EQ, NO...SKIP 10$: MOV U.ACB-U.TSTA(R5),R0 ;GET ACB ADD #A.SMAP,R0 ;POINT TO TRANSFER PARAMETERS BIT #S1.IBF,(R5) ;ARE WE DOING BUFFERED INPUT? BEQ 20$ ;IF EQ, NO...SKIP MOV R1,R2 ;COPY INPUT BUFFER ADDRESS CMP (R2)+,(R2)+ ;POINT PAST LINK AND COUNT WORDS MOV R5,(R2)+ ;SAVE R5 IN INPUT BUFFER MOV R3,(R2)+ ;ALSO SAVE PACKET ADDRESS MOV (R0)+,(R2)+ ;SAVE ACD BUFFER APR BIAS (A.SMAP) MOV (R0)+,(R2)+ ;SAVE ACD BUFFER DISPLACEMENT (A.SBUF) MOV I.PRM+16(R3),(R2)+ ;SAVE TASK PCB ADDRESS MOV I.PRM(R3),(R2)+ ;SAVE TASK BUFFER APR BIAS OFFSET MOV (R0),(R2) ;SAVE ACD BUFFER LENGTH (A.SLEN) BR 30$ ;TRANSFER WILL OCCUR WHEN $FINBF CALLS US 20$: MOV R4,-(SP) ;SAVE R4 MOV (R0)+,R1 ;GET ACD BUFFER APR BIAS (A.SMAP) MOV (R0)+,R2 ;GET ACD BUFFER DISPLACEMENT (A.SBUF) SUB #20000,R2 ;CONVERT TO AN APR5 ADDRESS MOV (R0),R0 ;GET ACD BUFFER LENGTH (A.SLEN) MOV U.TIP-U.TTIC(R4),R3 ;GET TASK BUFFER APR BIAS MOV U.TIP+2-U.TTIC(R4),-(SP) ;SAVE TASK BUFFER DISPLACEMENT ADD R0,U.TIP+2-U.TTIC(R4) ;UPDATE DISPLACEMENT FOR NEXT TIME MOV (SP)+,R4 ;GET TASK BUFFER DISPLACEMENT CALL $BLXIO ;TRANSFER FROM ACD BUFFER TO TASK BUFFER MOV (SP)+,R4 ;RESTORE R4 MOV U.TCI-U.TTIC(R4),R3 ;RESTORE R3 BIC #UA.CAL,U.AFLG-U.TSTA(R5) ;SET DEFAULT PROCESSING MOV #A.CALL,R0 ;SET TRANSFER COMPLETION ENTRY POINT CALL $SWACD ;CALL ACD TO DEALLOCATE BUFFER BIT #UA.CAL,U.AFLG-U.TSTA(R5) ;ACD HAVE ANOTHER BUFFER TO COPY? BNE 10$ ;IF NE, YES...LOOP TO DO IT BIS #UA.TRA,U.AFLG-U.TSTA(R5) ;SET FLAG FOR CHECKING LATER 30$: .ENDC ;T$$ACD CLRB U.TITI-U.TTIC(R4) ;CLEAR INPUT TIMER BIT #S1.IBF,(R5) ;ARE WE DOING BUFFERED INPUT? BEQ SOLIDN ;IF EQ, NO...MUST BE SOLICITED INPUT, SO SKIP MOV (R1),R2 ;GET NEXT BUFFER (IF THERE IS ONE) CALL DELTB ;DEALLOCATE ALL REMAINING BUFFERS CLR (R1) ;THIS IS NOW THE LAST BUFFER ASSUME S1.USI,100000 TST (R5) ;ARE WE DOING UNSOLICITED INPUT? ; BMI USIDON ;IF MI, YES...SKIP TO FINISH IT BPL SOLIDN ;IF PL, NO...PROCESS SOLICITED INPUT JMP USIDON ;IF MI, YES...SKIP TO FINISH IT .PAGE .SBTTL . SOLIDN - SOLICITED INPUT COMPLETION ; ; SOLIDN - SOLICITED INPUT COMPLETED ; ; INPUTS: ; R3 => CURRENT I/O REQUEST PACKET ; R4 => U.TTIC OF THE TERMINAL UCBX ; R5 => U.TSTA OF THE TERMINAL UCB ; SOLIDN: CALL IRESEL ;RESET INPUT STATE FLAGS BIC #S1.IBY,(R5) ;INDICATE INPUT IS NOW IDLE BIC #S5.ITI,U.TST5-U.TSTA(R5) ;CLEAR IMMEDIATE TIMEOUT FLAG CLR U.TCI-U.TTIC(R4) ;CLEAR PACKET POINTER (U.TCI) MOV U.TRTT-U.TTIC(R4),R2 ;GET THE TERMINATOR TABLE ADDRESS BEQ 10$ ;IF EQ, NONE...SKIP CALL DETB ;DEALLOCATE THE TERMINATOR TABLE CLR U.TRTT-U.TTIC(R4) ;CLEAR TERMINATOR TABLE ADDRESS 10$: .IF DF T$$RPR MOV U.TFPB-U.TTIC(R4),R2 ;GET PROMPT BUFFER LIST BEQ 20$ ;IF EQ, NONE...SKIP CALL DELTB ;DEALLOCATE ALL PROMPT BUFFERS CLR U.TFPB-U.TTIC(R4) ;CLEAR POINTER 20$: .ENDC ;T$$RPR MOV I.PRM+4(R3),R1 ;GET MAXIMUM BYTE COUNT SUB (R4)+,R1 ;SUBTRACT REMAINING BYTES TO READ... ; ...YIELDING BYTES ACTUALLY READ TST (R3) ;COMPLETION STATUS ALREADY PRESENT? BNE 30$ ;IF NE, YES...SKIP TO COMPLETE THE INPUT INC (R3) ;BUFFER FULL - SET STATUS = IS.SUC .IF DF T$$ESC BIT #S1.ESC,(R5) ;IN THE MIDDLE OF AN ESCAPE SEQUENCE? BEQ 30$ ;IF EQ, NO...ALL IS OKAY SO SKIP MOV #IE.PES&377,(R3) ;SET ERROR FOR "PARTIAL ESCAPE SEQUENCE" BIC #S1.ESC,(R5) ;GET OUT OF ESCAPE SEQUENCE MODE CLRB U.TISV-U.TFIB(R4) ;CLEAR INPUT STATE VARIABLE .ENDC ;T$$ESC 30$: .IF DF T$$EIO ; ; IF THIS WAS AN IO.EIO AND THERE ARE MORE CHARACTERS IN THE TAB ; AND THE SYSTEM SUPPORTS ICS, REQUEST ICS NOTIFICATION. ; BIT #S6.EIO,U.TST6-U.TSTA(R5) ;WAS/IS THIS AN EXTENDED IO? BEQ 50$ ;IF NOT NO ICS .IF DF T$$ICS MOV R3,-(SP) ;SAVE REGISTER DESTROYED BY GCTAB CALL GCTAB ;ANY CHARACTERS SITTING IN TYPE-AHEAD? MOV (SP)+,R3 ;RESTORE REGISTER BCS 40$ ;IF CS, NO - SKIP FRKBIT BIS,#FR.ICS ;REQUEST ICS NOTIFICATION .ENDC ;T$$ICS 40$: BIC #S6.EIO!S6.RLU!S6.RDI,U.TST6-U.TSTA(R5);;CLEAR FLAGS 50$: .ENDC ;T$$EIO BIT #S1.IBF,(R5) ;ARE WE DOING BUFFERED INPUT? BEQ 70$ ;IF EQ, NO...SKIP ASSUME U.TFIB,U.TTIC+2 MOV (R4),R4 ;GET FIRST INPUT BUFFER (U.TFIB) MOV R4,I.PRM+12(R3) ;STORE POINTER IN PACKET FOR $FINBF .IF DF T$$SPL MOV KISAR6,I.PRM+14(R3) ;STORE MAPPING INFO FOR $FINBF SUB #200,I.PRM+14(R3) ;$FINBF EXPECTS MAPPING THROUGH APR 5 .IFF ;T$$SPL MOV KISAR5,I.PRM+14(R3) ;STORE MAPPING INFO FOR $FINBF .IFTF ;T$$SPL 60$: MOV (R4)+,R2 ;GET LINK TO NEXT BUFFER, POINT TO BYTE COUNT MOV #T$$BFL,(R4) ;SET TOTAL LENGTH OF BUFFER MOV R2,R4 ;GET NEXT BUFFER BNE 60$ ;IF NE, FOUND ONE...LOOP 70$: BIT #TF.XOF,I.FCN(R3) ;SEND XOFF AT INPUT COMPLETION? BEQ 80$ ;IF EQ, NO...SKIP ASSUME S3.FDX,200 TSTB 4(R5) ;IS THIS A FULL DUPLEX LINE? BMI 80$ ;IF MI, YES...TRANSMIT MAY BE BUSY SO SKIP XOF MOV R3,-(SP) ;SAVE R3 MOV #ASXOFF,R3 ;POINT TO XOFF CHARACTER .IFT ;T$$SPL MOV #120000,R4 ;SET VIRTUAL ADDRESS OF UCBX .IFF ;T$$SPL MOV U.TUX-U.TSTA(R5),R4 ;GET UCBX .ENDC ;T$$SPL CALL ECHRL ;"ECHO" XOFF WITH INTERRUPTS LOCKED OUT MOV (SP)+,R3 ;RESTORE R3 80$: .IF DF T$$ACD MOV U.ACB-U.TSTA(R5),R2 ;GET ACB BEQ 90$ ;IF EQ, TERMINAL DOESN'T HAVE ONE...SKIP BIT #UA.TRA,U.AFLG-U.TSTA(R5) ;DOING TRANSFER NOW? BEQ 90$ ;IF EQ, NO...SKIP MOV A.IOS+2(R2),R1 ;GET TRANSFER LENGTH FROM ACB BIT #S1.IBF,(R5) ;DOING A BUFFERED READ? BEQ 90$ ;IF EQ, NO...SKIP INC I.PRM+12(R3) ;SET BUFFER ADDRESS ODD FOR NON-STD $FINBF USE 90$: .ENDC ;T$$ACD CALLR DONE ;COMPLETE THE CURRENT INPUT REQUEST .PSECT MAP5 .PAGE .SBTTL . NXTOB - GET NEXT OUTPUT BUFFER ; ;+ ; **-NXTOB - GET NEXT OUTPUT BUFFER. ; ; *** NOTE *** THIS ROUTINE IS CALLED AT DEVICE PRIORITY FROM THE OUTPUT ; INTERRUPT SERVICE ROUTINE ;. ; INPUTS: ; R4 => U.TOP+2 OF THE TERMINAL UCBX ; R5 => U.TSTA OF THE TERMINAL UCB ; ; OUTPUTS: ; IF THERE IS ANOTHER OUTPUT BUFFER LINKED: ; CC-Z = 0 ; R4 => U.TOC OF THE TERMINAL UCBX ; U.TOP, U.TOP+2, U.TOC UPDATED FOR NEXT BUFFER ; ; IF NOTHING MORE TO OUTPUT: ; CC-Z = 1 ; R4 => U.TOP OF THE TERMINAL UCBX ; ; REGISTERS MODIFIED: R2, R4 ;- ; NXTOB:: .IF DF T$$ACD BIT #S2.OBF,2(R5) ;;;ARE WE DOING BUFFERED OUTPUT? BEQ 10$ ;;;IF EQ, NO...RETURN WITH CC-Z = 1 .ENDC ;T$$ACD MOV -(R4),R2 ;;;GET START OF CURRENT BUFFER (U.TOP) BEQ 10$ ;;;IF EQ, THIS WAS AN ECHO...EXIT WITH CC-Z = 1 MOV (R2),R2 ;;;GET START OF NEXT BUFFER BEQ 10$ ;;;IF EQ, NONE...RETURN WITH CC-Z = 1 MOVB OPTIMR,U.TOTI-U.TOP(R4) ;;;SET UP THE OUTPUT TIMER JMP UPUB ;;;GO AND UPDATE THE UCB 10$: RETURN ;;;RETURN WITH CC-Z = 1 .SBTTL . USIDON - UNSOLICITED INPUT HAS COMPLETED ; ; USIDON - UNSOLICITED INPUT COMPLETED. ; ; THIS ROUTINE WILL ALLOCATE A CLI COMMAND BUFFER IN THE SYSTEM POOL. ; THE INPUT BUFFERS ARE THEN COPIED INTO THE CLI BUFFER AND IT IS QUEUED ; TO THE CLI TASK. IF CONTINUATION LINES ARE TO FOLLOW (LAST CHARACTER ; OF THIS BUFFER IS A HYPHEN), SIMULATE A CONTRTL-C. ; ; INPUTS: ; SECOND WORD OF FIRST RECEIVE BUFFER: ; <0 - ERROR ; 0 - BUFFER FULL ; IS.SUC - SUCCESS ; IS.TMO - TIME-OUT ; >IS.TMO - CTRL-U COMPLETED ; USIDON: MOV #M$$CRB-4+1,-(SP) ;GET MAX LENGTH OF CLI COMMAND ;PLUS 1 FOR TERMINATOR SUB (R4)+,(SP) ;GET NUMBER OF BYTES READ PLUS 1 CMP (R3),#IS.TMO ;TIME-OUT? BEQ 50$ ;Y - JUMP CMPB (R3)+,#IS.SUC ;TEST STATUS BLO 50$ ;BUFFER FULL - JUMP BLT 40$ ;ERROR - JUMP BGT 30$ ;CTRL-U COMPLETED - JUMP ;ELSE SUCCESS! TST $MCRPT ;IS MCR DISPATCHER INSTALLED? BEQ 50$ ;IF NOT THEN ECHO ^U TO TELL USER .IF DF T$$SPC BIC #UM.KIL,U.MUP-U.TSTA(R5) ;RESET CLI CONTINUATION LINE STATUS .ENDC ;T$$SPC .IF DF T$$SER MOV #CC.TTD,-(SP) ;ASSUME NEED TO SET CC.TTD IN CLI PACKET TSTB U.TFPB-U.TFIB(R4) ;HERE BECAUSE USER TYPED CTRL-C? BEQ 10$ ;N - JUMP BIT #UM.CMD,U.MUP-U.TSTA(R5) ;COMMAND ALREADY IN PROGRESS? BEQ 10$ ;N - NOTHING UNUSUAL THEN CLR (SP) ;DON'T SET CC.TTD SO THAT COMPLETION OF THE ;COMMAND WE ARE ABOUT TO SEND WON'T AFFECT ;THE SERIAL PROCESSING ALREADY IN USE 10$: MOV (SP)+,U.TFPB-U.TFIB(R4) ;GET ZERO OR CC.TTD BIT BIC #UM.CMD,U.MUP-U.TSTA(R5) ;RESET COMMAND IN PROGRESS BIT BIT #UM.SER,U.MUP-U.TSTA(R5) ;CLI TYPEAHEAD ENABLED? BEQ 20$ ;N - JUMP BIS #UM.CMD,U.MUP-U.TSTA(R5) ;Y - SHOW A COMMAND IS UNDERWAY 20$: .ENDC ;T$$SER CMP (SP),#1 ;ONE BYTE READ? (MUST BE A RETURN) BNE 100$ ;N - JUMP .IF DF T$$SPC MOV #CC.PRM,R1 ;SET PROMPT REQUEST STATUS BIT BIS U.TFPB-U.TFIB(R4),R1 ;OR IN POSSIBLE CC.TTD BIT MOV R5,R2 ;GET UCB ADDRESS SUB #U.TSTA,R2 ; CALL $QCNTP ;QUEUE PROMPT REQUEST TO THE CLI .IFF ;T$$SPC MOV #4,R1 ;Y - ONLY ALLOCATE 4 BYTES FROM THE DSR CALL $ALOCB ; BCS 50$ ;FAILED - JUMP MOV R0,R1 ;SAVE ADDRESS TST (R0)+ ;SKIP PAST LINK WORD MOV R5,(R0) ;INSERT UCB ADDRESS SUB #U.TSTA-1,(R0) ;+1 TO INDICATE A SPECIAL MCR PACKET BR 140$ ;QUEUE THIS SHORT PACKET TO THE CLI .IFTF ;T$$SPC 30$: BR 200$ ;BRANCH AIDS 40$: BR 210$ ; 50$: JMP 220$ 100$: .IFT ;T$$SPC MOV (SP),R1 ;GET CHARACTER COUNT ADD #C.CTXT+77,R1 ;ROUND UP TO NEXT 32 WORD BOUNDARY ASH #-6,R1 ;COMPUTE NUMBER OF SECONDARY POOL BLOCKS NEEDED CALL $ALSEC ;ALLOCATE CLI BUFFER BCS 220$ ;FAILURE - JUMP MOVB (R3),-(SP) ;SAVE TERMINATOR .IF NDF T$$SPL MOV U.TFPB-U.TFIB(R4),-(SP) ;SAVE CLI STATUS WORD .IFTF ;NDF T$$SPL MOV R0,KISAR6 ;MAP CLI BUFFER MOV #140002,R2 ;POINT TO IT MOV $MCRPT,(R2)+ ;SET CLI DISPATCHER TCB ADDRESS MOV R5,(R2) ;SET UCB ADDRESS SUB #U.TSTA,(R2)+ ; .IFT ;NDF T$$SPL MOV 4(SP),(R2) ;SET CHARACTER COUNT .IFF ;NDF T$$SPL MOV 2(SP),(R2) ;SET CHARACTER COUNT .IFTF ;NDF T$$SPL DEC (R2)+ ;LESS TERMINATOR .IFT ;NDF T$$SPL MOV (SP)+,(R2)+ ;SET STATUS BIT .IFF ;NDF T$$SPL MOV U.TFPB-U.TFIB(R4),(R2)+ ;SET STATUS BIT .ENDC ;NDF T$$SPL CLR (R2)+ ;CLEAR TEXT STARTING OFFSET MOVB (SP)+,(R2)+ ;INSERT TERMINATOR MOVB R1,(R2)+ ;SET NUMBER OF SECONDARY POOL BLOCKS USED MOV $DALED,KISAR6 ;REMAP DRIVER MOV (R4),R1 ;GET FIRST BUFFER (U.TFIB) MOV R4,-(SP) ;SAVE UCBX POINTER MOV R2,R4 ;CHANGE HANDS MOV 2(SP),R2 ;GET CHARACTER COUNT MOV R5,-(SP) ;SAVE UCB POINTER .IFF ;T$$SPC MOV #M$$CRB,R1 ;GET SIZE OF CLI BUFFER CALL $ALOCB ;ALLOCATE CLI BUFFER BCS 220$ ;FAILURE - JUMP MOVB (R3),@U.TIP+2-U.TFIB(R4) ;STORE TERMINATOR IN BUFFER MOV (SP),R2 ;GET TOTAL NUMBER OF CHARACTERS READ ;PLUS TERMINATOR MOV R0,-(SP) ;SAVE CLI COMMAND BUFFER ADDRESS TST (R0)+ ;SKIP LINK WORD MOV R5,(R0) ;INSERT UCB ADDRESS SUB #U.TSTA,(R0)+ ; MOV (R4),R1 ;GET FIRST BUFFER (U.TFIB) .IFTF ;T$$SPC 110$: MOV (R1)+,-(SP) ;SAVE LINK TO NEXT BUFFER TST (R1)+ ;SKIP SECOND WORD MOV #T$$BFL-4,R3 ;GET MAX NUMBER OF BYTES IN BUFFER CMP R3,R2 ;TOO MANY? BLE 120$ ;N - JUMP MOV R2,R3 ;Y - ADJUST 120$: SUB R3,R2 ;GET NUMBER OF BYTES STILL TO GO 130$: .IFT ;T$$SPC MOVB (R1)+,R5 ;GET NEXT CHARACTER FROM DRIVER BUFFER MOV R0,KISAR6 ;MAP CLI BUFFER MOVB R5,(R4)+ ;PUT CHARACTER IN CLI BUFFER MOV $DALED,KISAR6 ;REMAP DRIVER BUFFER .IFF ;T$$SPC MOVB (R1)+,(R0)+ ;COPY INTO CLI BUFFER .IFTF ;T$$SPC DEC R3 ;DECREMENT BYTE COUNT BGT 130$ ;IF GT, LOOP FOR MORE TO COPY MOV (SP)+,R1 ;GET NEXT BUFFER BNE 110$ ;THERE IS ONE - LOOP .IFT ;T$$SPC MOV R0,KISAR6 ;MAP CLI BUFFER MOVB #CH.CR,-(R4) ;DELIMIT BUFFER WITH A CARRIAGE RETURN MOVB -(R4),4(SP) ;SAVE LAST INPUT CHARACTER MOV $DALED,KISAR6 ;REMAP DATASPACE MOV (SP)+,R5 ;RESTORE UCB POINTER MOV (SP)+,R4 ;RESTORE UCBX POINTER MOV R0,R1 ;GET SECONDARY POOL COMMAND BUFFER ADDRESS CALL $QCPKT ;QUEUE CLI COMMAND BUFFER .IFF ;T$$SPC MOV (SP)+,R1 ;GET CLI COMMAND BUFFER MOVB -2(R0),(SP) ;N - SAVE LAST INPUT CHARACTER 140$: CALL $QMCRL ;QUEUE CLI COMMAND BUFFER .ENDC ;T$$SPC .IF DF R$$MPL CMPB (SP),#'- ;WAS LAST CHARACTER A HYPHEN? .IF DF A$$CLI BNE 205$ ;N - JUMP MOV U.MUP-U.TSTA(R5),R2 ;GET CLI OFFSET BIC #^C,R2 ;SEPARATE OUT CLI INDEX MOV $CPTBL(R2),R2 ;POINT TO CLI PARSER BLOCK BIT #CP.SGL,C.PSTS(R2) ;CONTINUATION LINES ACCEPTED? .ENDC ;A$$CLI BEQ 300$ ;Y - CONTINUATION LINES TO FOLLOW, JUMP BR 205$ .IFTF ;R$$MPL 200$: .IFT ;R$$MPL TST U.TFPB-U.TFIB(R4) ;ARE WE DOING A CONTINUATION LINE? BPL 205$ ;PL - NO -BRANCH FRKBIT BIS,#FR.KIL ;AN ERROR OCCURED, SO KILL THE CONTIN. LINE. 205$: .ENDC ;R$$MPL TST (SP)+ ;CLEAN STACK CALL IRESEL ;RESET INPUT STATE FLAGS BIC #S1.USI!S1.IBY,(R5) ;CLEAR ADDITIONAL INPUT STATE FLAGS CLR U.TFPB-U.TFIB(R4) ;CLEAN UP TEMPORARY VARIABLE WE USED FRKBIT BIS,#FR.GRQ ;TRY TO GET ANOTHER REQUEST PACKET CLR U.TCI-U.TFIB(R4) ;CLEAR PACKET POINTER (U.TCI) MOV (R4),R2 ;GET FIRST INPUT BUFFER CALLR DELTB ;DEALLOCATE ALL INPUT BUFFERS AND RETURN ; ; ERROR DURING UNSOLICITED INPUT. THESE ERRORS ARE: ; 1. FAILURE TO ALLOCATE CLI COMMAND BUFFER ; 2. TIME-OUT ; 3. BUFFER FULL WITH NO TERMINATOR ; IN EITHER CASE, SIMULATE A CTRL-U. ; 210$: CMPB -(R3),#IE.EOF ;END-OF-FILE (CTRL-Z TYPED)? BEQ 200$ ;Y - DON'T ECHO ^U (^Z ALREADY ECHOED) 220$: BIT #S1.OBY,(R5) ;OUTPUT BUSY? BNE 200$ ;Y - WE CANNOT BEGIN OUTPUT OF A ^U BECAUSE ;OUTPUT IS ALREADY BUSY. WE CAN'T DO ;ANYTHING BUT GIVE UP 230$: MOVB #CH.CTU,(SP) ;GET CTRL-U CHARACTER ;(OVERWRITE OLD WORD ON STACK) BR 310$ ;REQUEST POST-FORK PROCESSING OF CTRL-U ; ; CLI CONTINUATION EXPECTED ; 300$: MOVB #CH.CTC,(SP) ;GET CTRL-C CHARACTER (OVER OLD WORD ON STACK) .IF DF T$$SPC MOV #100000,U.TFPB-U.TFIB(R4) ;SET CLI CONTINUATION PROMPT .ENDC ;T$$SPC 310$: ;REFERENCE LABEL .IF DF T$$SER BIC #UM.CMD,U.MUP-U.TSTA(R5) ;SHOW NO CLI COMMANDS IN PROGRESS .ENDC ;T$$SER .IF DF T$$MOD BITB #US.DSB!US.CRW,U.STS-U.TSTA(R5) ;LINE DISABLED OR WAITING FOR CARRIER? BNE 200$ ;Y - JUMP .ENDC ;T$$MOD .IF DF T$$SPL MOVB (SP)+,U.TECO-U.TSTA(R5) ;LOAD CHARACTER FOR POST-FORK .IFF ;T$$SPL MOVB (SP)+,U.TECB-U.TFIB(R4) ;LOAD CHARACTER FOR POST-FORK .ENDC ;T$$SPL ;PROCESSING IN ECHO BUFFER FRKBIT BIS,# ;TRY TO GET ANOTHER PACKET (FR.GRQ) ;REQUEST POST-FORK PROCESSING ;TRY TO GET ANOTHER PACKET (FR.GRQ) ;REQUEST POST-FORK PROCESSING (FR.PFP) RETURN ;RETURN .PAGE .SBTTL OUTPUT REQUEST PRE-PROCESSING .SBTTL . PPWLB - WRITE-SPECIAL-DATA REQUEST ; ;+ ; **-PPWSD - WRITE SPECIAL DATA ; **-PPRPR - WRITE THE PROMPT OF A READ-AFTER-PROMPT ; **-PPWLB - WRITE-LOGICAL-BLOCK ; ; INPUTS: ; R3 I/O PACKET ADDRESS ; I.LNK = 0 ; R4 UCBX ADDRESS ; R5 POINTER TO U.TSTA ; ; .ENABL LSB .IF DF B$$MAP PPWSD:: BIC #TF.RCU!TF.WBT,I.FCN(R3) ;CLEAR DISALLOWED BITS MOVB I.PRM+10(R3),U.TDYP(R4) ;STORE THE DATA TYPE (4TH PARM) CLR I.PRM+10(R3) ;NO VFC OR CURSOR POSITIONING ALLOWED (FOR CUP) CLR I.PRM+6(R3) ;NO VFC OR CURSOR POSITIONING ALLOWED BR WLB1 ;DO THE OUTPUT .ENDC ;B$$MAP .SBTTL . PPRPR - WRITE PROMPT OF A READ-AFTER-PROMPT .IF DF T$$RPR PPRPR:: CLRB I.FCN+1(R3) ;WIPE OUT HIGH BYTE FOR LATER CHECKS IN PPRLB MOV R3,R2 ;COPY PACKET POINTER ADD #I.PRM+16,R2 ;POINT TO I.PRM+16 MOV (R2),-(SP) ;SAVE 2.ND WORD OF ADDRESS DOUBLE WORD MOV -(R2),2(R2) ;MOVE VFC/CURSOR-CONTROL TO I.PRM+16 MOV -(R2),2(R2) ;MOVE BYTE COUNT TO I.PRM+14 MOV (SP)+,(R2) ;MOVE 2.ND WORD OF ADW TO I.PRM+12 PPRPR1: INC (R3) ;SET STATUS NON-ZERO TO INDICATE IO.RPR ;(FOR EASIER CHECKING) CLR U.TFOB(R4) ;CLEAR POINTER TO FIRST OUTPUT BUFFER .IF DF B$$MAP CLRB U.TDYP(R4) ;INDICATE DATA TYPE 0, TEXT .ENDC ;B$$MAP BR WLB2 ;BYPASS TF.CCO CHECK .ENDC ;T$$RPR .SBTTL . PPWLB - WRITE-LOGICAL-BLOCK REQUEST ; ; PPWLB - WRITE LOGICAL BLOCK ; PPWLB:: .IF DF T$$CUP MOV I.PRM+10(R3),I.PRM+6(R3) ;MOVE VFC TO RIGHT PLACE .ENDC ;T$$CUP .IF DF B$$MAP CLRB U.TDYP(R4) ;INDICATE DATA TYPE 0, TEXT WLB1: .ENDC ;B$$MAP BIT #TF.CCO,I.FCN(R3) ;CANCEL CTRL-O? BEQ WLB3 ;N - JUMP WLB2: BIC #S2.CTO,2(R5) ;Y - DO IT WLB3: BIT #S2.CTO,2(R5) ;OUTPUT STOPPED BY CTRL-O? ;(CAN ONLY HAPPEN IF TERM. IS ATTACHED) BNE 10$ ;Y - FINISH DIRECTLY CALL ALTB ;ALLOCATE AN INTERMEDIATE BUFFER BCC 30$ ;IF CC, GOT ONE...SKIP .IF DF T$$EIO MOV U.TDIF(R4),R2 ;GET FIRST DEFAULT INPUT BUFFER, IF ANY CALL DELTB ;DEALLOCATE DEFAULT INPUT BUFFERS CLR U.TDIF(R4) ;CLEAR POINTER .ENDC ;T$$EIO MOV #IE.NOD&377,R0 ;ERROR - NO BUFFER AVAILABLE BR 20$ ;SKIP 10$: MOV #IS.SUC,R0 ;SUCCESS 20$: JMP IOFIN ;FINISH THE OUTPUT REQUEST 30$: MOV R3,U.TCO(R4) ;U.TCO <-- PACKET ADDRESS MOVB I.FCN(R3),R0 ;GET IO SUBFUNCTION CODE .IF DF T$$RPR TST (R3) ;PROMPT FOR IO.RPR? BEQ 40$ ;N - JUMP ASSUME TF.WAL,TF.BIN*4 ASL R0 ;SHIFT SUBF. CODE LEFT 2 BITS ASL R0 .IF DF T$$CUP ASSUME TF.RCU,S2.RCU BIC #TF.RCU,R0 ;CAN'T DO CURSOR RESTORE WITH IO.RPR .ENDC ;T$$CUP BIS #S1.IBY,(R5) ;SET INPUT BUSY ADD #10,R3 ;ADVANCE PACKET POINTER SO OFFSET I.PRM ;FROM R3 POINTS AT PROMPT PARAMETERS MOV R2,U.TFPB(R4) ;SAVE POINTER TO FIRST PROMPT BUFFER .ENDC ;T$$RPR 40$: ASSUME S2.WAL,TF.WAL ASSUME S2.RCU,TF.RCU BIC #^C,R0 ;CLEAR ALL BUT WAL AND RCU SUBFUNCTIONS TST (R5)+ ;POINT TO STATUS WORD 2 BIC #S2.WAL!S2.PCU!S2.RCU,(R5) ;CLEAR OLD FLAGS BIS R0,(R5) ;OR INTO STATUS WORD 2 MOV R4,R1 ADD #U.TOC,R1 ;POINT TO U.TOC CLR (R1)+ ;CLEAR U.TOC ASSUME U.TTOC,U.TOC+2 MOV I.PRM+4(R3),(R1)+ ;U.TTOC <-- TOTAL BYTE COUNT ASSUME U.TFOB,U.TTOC+2 MOV R2,(R1) ;LINK BUFFER TO LISTHEAD ; ; INTERPRET AND SAVE VERTICAL FORMAT CONTROL ; BIC #S2.CR,(R5) ;ASSUME NO TRAILING CR .IF DF T$$CUP TSTB I.PRM+7(R3) ;CURSOR POSITION SPECIFIED? BEQ 50$ ;N - JUMP MOV I.PRM+6(R3),U.TOC(R4) ;Y - SAVE CURSOR POS. IN U.TOC BIS #S2.PCU,(R5) ;SET FLAG BR 80$ ; 50$: .ENDC ;T$$CUP MOV #VFCRT,R0 ;POINT TO RECOGNITION TABLE FOR VFC 60$: TSTB (R0)+ ;END OF TABLE? BMI 70$ ;Y - JUMP CMPB -1(R0),I.PRM+6(R3) ;MATCH? BNE 60$ ;N - LOOP 70$: SUB #CHRT+1,R0 ;GET INDEX IN CHRD TABLE ASL R0 ;MAKE WORD INDEX MOVB CHRD(R0),U.TVFC(R4) ;STORE ENCODED VFC IN UCB ;(SEE MODULE "TTDAT" FOR CODING) ASSUME ,0 BISB CHRD+1(R0),1(R5) ;SAVE CR FLAG IN U.TSTA+2 80$: TST -(R5) ;POINT TO STATUS WORD 1 .IF DF T$$RPR MOV U.TCO(R4),R0 ;GET REAL PACKET POINTER MOV SP,I.PRM+16(R0) ;ASSUME WE CAN BUFFER ALL OUTPUT IN ;ONE LIST - MAKE I.PRM+16 NON-ZERO .IFF ;T$$RPR MOV SP,I.PRM+16(R3) ;ASSUME WE CAN BUFFER ALL OUTPUT IN ;ONE LIST - MAKE I.PRM+16 NON-ZERO .ENDC ;T$$RPR .DSABL LSB .PAGE .SBTTL OUTPUT REQUEST BUFFER HANDLING .SBTTL . WRITE1 - FILL OUTPUT BUFFERS ; ;+ ; **-WRITE1 - FILL OUTPUT BUFFERS WITH OUTPUT DATA. ; ; INPUTS: ; U.TFOB POINTER TO FIRST OUTPUT BUFFER ; R3 POINTER TO PACKET ; (ADVANCED 4 WORDS IF IO.RPR) ; R4 POINTER TO UCBX ; R5 POINTER TO U.TSTA ; U.TCHP CURRENT HORIZONTAL POSITION ; U.TCVP CURRENT VERTICAL POSITION ; U.TVFC ENCODED VERTICAL FORMAT CONTROL ;- ; WRITE1: .IF DF T$$RPR ASSUME U.TCHP&1,0 ASSUME U.TCVP,U.TCHP+1 MOV U.TCHP-U.TSTA(R5),-(SP) ;SAVE CURRENT HOR. AND VERT. POS. .ENDC .IF DF T$$CUP ; SAVE CURRENT HORIZONTAL AND VERTICAL POSITION IN CASE ; CURSOR RESTORE IS REQUESTED. ; ASSUME U.TSHP&1,0 ASSUME U.TSVP,U.TSHP+1 .IF DF T$$RPR MOV (SP),U.TSHP(R4) .IFF ;T$$RPR MOV U.TCHP-U.TSTA(R5),U.TSHP(R4) .ENDC ;T$$RPR MOV #EXPC3,EXPCP ;SET POINTER TO EXPC3 .IFTF ;T$$CUP ; ; CHECK IF 'PURE' IO.WAL. IF IT IS 'PURE', MEANING NO VFC, CURSOR POSITIONING, ; ETC. TRANSFER IS DONE DIRECTLY FROM A TASK BUFFER, OTHERWISE TRANSFER IS ; DONE THROUGH INTERMEDIATE TTDRV BUFFERS ; .IF DF T$$DMA BIT #S2.WAL,2(R5) ;DOING IO.WAL? BEQ 5$ ;NO BIT #S5.DMA,U.TST5-U.TSTA(R5) ;CHECK FOR DMA DEVICE BEQ 5$ ;NO. SETUP INTERNAL BUFFERS BIT #S1.IBY,(R5) ;CHECK IF IO.RPR!TF.BIN IN PROGERSS BNE 5$ ;YES. SETUP REGULAR OUTPUT .IF DF T$$CUP BIT #S2.PCU!S2.RCU!S2.CR,2(R5) ;CURSOR POS. REQUESTED? .IFF ;DF T$$CUP BIT #S2.CR,2(R5) ;CARRIAGE RETURN AT THE END? .IFTF ;DF T$$CUP BNE 5$ ;YES. SETUP INTERNAL BUFFERS .ENDC ;DF T$$CUP TSTB U.TVFC(R4) ;CHECK FOR VFC BNE 5$ ;YES. SETUP INTERNAL BUFFERS MOV U.TCO(R4),R3 ; MOV R1,-(SP) ;SAVE R1. $TSTBF WILL KILL IT CALL $TSTBF ;CHECK IF TASK IS FIXED BCC 3$ ;NOT FIXED - USE INTERMEDIATE BUFFER .IF LT T$$BFL-12 ;CHECK IF BUFFER HAS ENOUGH SPACE .ERROR .ENDC ; ;SETUP TRANSFER FROM A TASK BUFFER ; MOV U.TFOB(R4),R2 ;GET BUFFER ADDR MOV I.PRM(R3),R1 ;GET TASK BUFFER CLR R0 ; ASHC #6,R0 ;GET PHYS. ADDR CLR (R2)+ ;CLEAR LINK WORD FOR WAL TST (R2)+ ;STEP TO NEXT OFFSET MOV U.TTOC(R4),(R2)+ ;SETUP COUNTER MOV R0,(R2)+ ;GET HIGH 6 BITS MOV I.PRM+2(R3),(R2) ;GET VIRTUAL ADDRESS BIC #160000,(R2) ;CONVERT TO OFFSET ADD R1,(R2) ;GET LOW ADDR ADC -(R2) ;ADJUST HIGH BITS CLR U.TTOC(R4) ;CLEAR TOTAL BYTE COUNTER IN UCBX MOV (SP)+,R1 ;RESTORE R1 (SAVED BEFORE $TSTBF) BIC #S2.FLF,2(R5) ;;CLEAR FORCE-LF FLAG (LF IS FORCED ONLY ;ON ECHO, NOT ON TASK OUTPUT) BIS #S5.DWA,U.TST5-U.TSTA(R5); SET DMA IO.WAL IN PROGRESS JMP 80$ ;GO ON 3$: MOV (SP)+,R1 ;RESTORE R1 5$: .ENDC ;T$$DMA MOV U.TFOB(R4),R0 ;GET FIRST BUFFER IN R0 MOV #SETOBF,-(SP) ;FIRST SET UP NEW BUFFER .IFT ;T$$CUP BIT #S2.PCU,2(R5) ;CURSOR POS. REQUESTED? BEQ 10$ ;N - JUMP MOV U.TOC(R4),R2 ;Y - GET CURSOR COORDINATES SUB #401,R2 ;ADJUST TO BASE 0 MOV #CPOS,EXPCP ;SET POINTER TO CURSOR POS. ROUTINE CALL @(SP)+ ;CALL COROUTINE MOV #EXPC3,EXPCP ;RESTORE POINTER TO EXPC3 BIC #S2.PCU,2(R5) ;CLEAR FLAG BR 40$ ; .ENDC ;T$$CUP ; ; CHECK IF ANY LEADING LF'S SHOULD BE INSERTED ; 10$: TSTB U.TVFC(R4) ;GET VFC CHARACTER BEQ 40$ ;NO LEADING LF OR FF - JUMP .IF DF T$$RPR&T$$EIO BIT #S6.EIO,U.TST6-U.TSTA(R5) ;WAS THIS AN EXTENDED I/O? BEQ 15$ ;BR IF NOT MOV U.TCO(R4),R2 ;GET SAVED OUTPUT PACKET TST (R2) ;IS THIS IO.RPR BEQ 15$ ;IF EQ, NO TSTB U.TCHP-U.TSTA(R5) ;AT LEFT (OTHER RIGHT) MARGIN? BNE 40$ ;IF NE NO, JUMP AND PRAY 15$: .ENDC ; DF T$$RPR&T$$EIO MOVB U.TVFC(R4),R2 ;GET VFC CHARACTER BPL 30$ ;FF - JUMP 20$: MOVB #CH.LF,R2 ;ONE OR MORE LF'S 30$: CALL @(SP)+ ;INSERT INCB U.TVFC(R4) ;ANY MORE LF'S? BEQ 35$ ;N - JUMP BMI 20$ ;Y - LOOP CLRB U.TVFC(R4) ;JUST DID A FF - CLEAR ; ; INSERT CHARACTERS FROM TASK BUFFER ; 35$: .IF DF T$$RPR&T$$EIO BIT #S6.EIO,U.TST6-U.TSTA(R5) ;WAS THIS AN EXTENDED I/O? BEQ 40$ ;BR IF NOT MOV U.TCO(R4),R2 ;GET SAVED OUTPUT PACKET TST (R2) ;IS THIS IO.RPR BEQ 40$ ;IF EQ, NO BIS #S2.ELF,2(R5) ;SET THE EAT-A-LINEFEED BIT .ENDC ; DF T$$RPR&T$$EIO 40$: ;REFERENCE LABEL .IF DF T$$ACD TST U.ACB-U.TSTA(R5) ;DOES THIS TERMINAL HAVE AN ACD? BEQ 48$ ;N - JUMP BIT #UA.TRN,U.AFLG-U.TSTA(R5) ;IN THE MIDDLE OF A TRANSLATION? BNE 44$ ;Y - CONTINUE FROM POINT OF INTERRUPTION TST U.TTOC(R4) ;HAVE WE ALREADY BEEN THROUGH THIS CODE PATH? BEQ 60$ ;Y - JUST OUTPUT A TRAILING CR 42$: BIC #UA.TRN,U.AFLG-U.TSTA(R5) ;SET DEFAULT PROCESSING MOV R0,-(SP) ;SAVE R0 MOV #A.TRAN,R0 ;SET OUTPUT CHARACTER TRANSLATION ENTRY POINT CALL $SWACD ;CALL ACD MOV (SP)+,R0 ;RESTORE R0 BIT #UA.TRN,U.AFLG-U.TSTA(R5) ;DOES ACD WANT TO PERFORM TRANSLATION? BEQ 48$ ;N - JUMP CLR U.TTOC(R4) ;ACD WILL DETERMINE NUMBER OF CHARACTERS OUTPUT 44$: MOV U.ACB-U.TSTA(R5),R2 ;GET ACB ADD #A.SMAP,R2 ;POINT TO SYSTEM STATE BUFFER PARAMETERS OFFSET 46$: MOV (R2)+,KISAR6 ;MAP BUFFER PASSED BY ACD MOVB @(R2)+,R2 ;GET CHARACTER FROM BUFFER MOV $DALED,KISAR6 ;RESTORE DRIVER MAPPING CALL @(SP)+ ;INSERT CHARACTER INTO TTDRV BUFFER MOV U.ACB-U.TSTA(R5),R2 ;GET ACB ADD #A.SMAP+2,R2 ;POINT TO SYSTEM STATE BUFFER ADDRESS INC (R2)+ ;UPDATE POINTER DEC @R2 ;DECREMENT COUNT BEQ 42$ ;ZERO - CALL ACD TO GET NEXT BUFFER IF ANY CMP -(R2),-(R2) ;BACKUP TO BUFFER ADDRESS DOUBLEWORD BR 46$ ;LOOP TO GET AND INSERT NEXT CHARACTER .ENDC ;T$$ACD 48$: TST U.TTOC(R4) ;ANY MORE CHARACTERS FROM TASK BUFFER? ;(THERE WON'T BE IF WE COME HERE FROM ;"FPORD" TO OUTPUT A TRAILING CR) BEQ 60$ ;N - JUMP 50$: MOV I.PRM(R3),KISAR6 ;MAP TASK BUFFER MOVB @I.PRM+2(R3),R2 ;GET NEXT CHARACTER MOV $DALED,KISAR6 ;RESTORE DRIVER MAPPING CALL @(SP)+ ;INSERT CHARACTER INC I.PRM+2(R3) ;UPDATE POINTER IN TASK BUFFER DEC U.TTOC(R4) ;DECREMENT TOTAL BYTE COUNT BNE 50$ ;MORE TO DO - LOOP ; ; CHECK IF TRAILING CARRIAGE RETURN REQUIRED ; 60$: BIT #S2.CR,2(R5) ;INSERT CR AT END? BEQ 70$ ;N - JUMP MOVB #CH.CR,R2 ;Y - DO IT CALL @(SP)+ ; BIC #S2.CR,2(R5) ;CLEAR CR AND ELF FLAG 70$: .IF DF T$$CUP BIT #S2.RCU,2(R5) ;CURSOR RESTORE REQUESTED? BEQ 80$ ;N - JUMP MOV U.TSHP(R4),R2 ;Y - GET SAVED CURSOR POS. MOV #CPOS,EXPCP ;SET POINTER TO CURSOR POS. ROUTINE CALL @(SP)+ ;CALL COROUTINE MOV #EXPC3,EXPCP ;RESTORE POINTER TO EXPC3 BIC #S2.RCU,2(R5) ;CLEAR FLAG .ENDC ;T$$CUP 80$: MOV -(R1),R2 ;GET POINTER TO NEXT BUFFER BEQ 90$ ;NO UNUSED BUFFERS - JUMP CLR (R1) ;END THE LIST WITH THE LAST USED BUFFER CLZ ;CLEAR CC-Z TO TELL DELTB TO DEALLOCATE A LIST CALL DELTB ;DEALLOCATE THE UNUSED BUFFERS 90$: .IF DF T$$RPR MOV U.TCO(R4),R3 ;RESTORE REAL PACKET POINTER .IFTF ;T$$RPR TST I.PRM+16(R3) ;DID WE MANAGE TO BUFFER ALL THE DATA ;IN ONE BUFFER LIST? BEQ WRITE2 ;N - JUMP CALL $TSTBF ;Y - TEST IF TASK CAN BE CHECKPOINTED BCS CLR16 ;N - JUMP .IFT ;T$$RPR TST (R3) ;IS THIS AN IO.RPR? BEQ 100$ ;N - JUMP .IF DF T$$EIO ASSUME S6.RDI,100000 TST U.TST6-U.TSTA(R5) ;READING WITH DEFAULT INPUT? BPL 95$ ;IF EQ NO, MUST ALLOCATE A BUFFER MOV U.TDIF(R4),U.TFIB(R4) ;USE DEFAULT INPUT BUFFERS FOR INPUT DATA BNE 100$ ;IF NE THERE ARE SOME BUFFERS TO USE BR CLR16 ;ELSE NOT ENOUGH AVAILABLE BUFFERS .ENDC ;T$$EIO 95$: CALL ALTB ;ALLOCATE FIRST INPUT BUFFER BCS CLR16 ;FAILED - JUMP MOV R2,U.TFIB(R4) ;OK - SAVE BUFFER POINTER .IFTF ;T$$RPR 100$: CALL $INIBF ;INITIALIZE INTERMEDIATE BUFFERING BR WRITE2 ;START OUTPUT CLR16: CLR I.PRM+16(R3) ;USE $IOFIN AT END .SBTTL . WRITE2 - START OUTPUT OF THE BUFFER LIST ; ; WRITE2 - START OUTPUT OF THE BUFFER LIST ; WRITE2: .IFT ;T$$RPR TST (R3) ;IO.RPR? BEQ 10$ ;N - JUMP BIS #S5.RPO,U.TST5-U.TSTA(R5) ;SET PROMPT OUTPUT IN PROGRESS CLR (R3) ;INITIALIZE STATUS 10$: CMP (SP)+,(SP)+ ;CLEAN STACK .IFF ;T$$RPR TST (SP)+ ;CLEAN STACK .ENDC ;T$$RPR MOV #STAXL,-(SP) ;START OUTPUT OF BUFFER LIST JMP LOCKI ; .PAGE .SBTTL . PRLF - OUTPUT LEADING LF FOR SOLICITED INPUT IF NEEDED ; ; PRLF - OUTPUT LEADING LF FOR SOLICITED INPUT AT LEFT MARGIN ; PRLF: .IF DF T$$SPL MOV #120000,R4 ;SET VIRTUAL ADDRESS OF UCBX .IFF ;T$$SPL MOV U.TUX-U.TSTA(R5),R4 ;GET UCBX .ENDC ;T$$SPL CALL EXCR1 ;EXPAND A CARRIAGE RETURN (YIELDING LF!) MOV #ECHSTR,-(SP) ;OUTPUT LF JMP LOCKI .PAGE .SBTTL . INSERT - INSERT (EXPANSION OF) CHARACTER IN BUFFER. ; ;+ ; INSERT - INSERT (THE EXPANSION OF) ONE CHARACTER IN THE CURRENT OUTPUT BUFFER. ; ; INPUTS: ; R0 CURRENT POINTER IN OUTPUT BUFFER ; R1 POINTER TO SECOND WORD IN CURRENT OUTPUT BUFFER ; R2 CHARACTER TO INSERT ; R4 POINTER TO UCBX ; R5 POINTER TO U.TSTA ; ; OUTPUT: ; 1. IF (THE EXPANSION OF) THE CHARACTER FITS IN THE CURRENT BUFFER, ; OR IF IT DOES NOT BUT ANOTHER BUFFER IS SUCCESSFULLY ALLOCATED ; AND LINKED TO THE OLD BUFFER, THE CHARACTER IS INSERTED ; AND THE CALLER IS CALLED BACK AS A COROUTINE WITH: ; R0 UPDATED ; R1 POINTER TO SECOND WORD IN CURRENT BUFFER ; (MAY BE A NEW BUFFER) ; R2 DESTROYED ; R3-R5 UNCHANGED ; THE CALLER MAY NOW LOAD ANOTHER CHARACTER IN R2 AND ; HAVE IT INSERTED BY A "CALL @(SP)+" INSTRUCTION. ; ; 2. ELSE, IF THIS IS THE PROMPT FOR AN IO.RPR, THE HORIZONTAL ; AND VERTICAL POSITION AND THE WRAP-AROUND CONTEXT ; IS RESTORED, AND THE ERROR IE.NOD IS RETURNED TO ; THE TASK. (NO RETURN TO CALLER). ; ; 3. ELSE, OUTPUT IS STARTED WITH THE CURRENT LIST OF BUFFERS. ; (NO RETURN TO CALLER). ;- ; .ENABL LSB INSERT: MOV R3,-(SP) ;SAVE R3 10$: CLR -(SP) ;CLEAR FLAG MOV R2,-(SP) ;SAVE CHARACTER ASSUME U.TCHP&1,0 ASSUME U.TCVP,U.TCHP+1 MOV U.TCHP-U.TSTA(R5),-(SP) ;SAVE CURRENT POSITION MOV 2(R5),-(SP) ;SAVE WRAP-AROUND CONTEXT ;(IF EXPANDED STRING DOES NOT FIT) BIC #S2.FLF,2(R5) ;CLEAR FORCE-LF FLAG (LF IS FORCED ONLY ;ON ECHO, NOT ON TASK OUTPUT) .IF DF T$$CUP CALL @EXPCP ;EXPAND CHAR. OR CURSOR POS. COMMAND .IFF ;T$$CUP CALL EXPC3 ;EXPAND CHARACTER .ENDC ;T$$CUP BVC 15$ ;IF V IS SET, THIS CHAR. IS TO BE DISCARDED ASL 6(SP) ;CLEAR SAVED CARRY BR 40$ ;GO TO RESTORE STACK 15$: BEQ 30$ ;SINGLE CHARACTER EXPANSION - JUMP ROL 6(SP) ;SAVE CC-C ADD R2,(R1) ;UPDATE BUFFER BYTE COUNT CMP (R1),#T$$BFL-4 ;DOES STRING FIT? BHI 50$ ;N - JUMP 20$: MOVB (R3)+,(R0)+ ;COPY STRING INTO BUFFER SOB R2,20$ ;LOOP BR 40$ 30$: CMP (R1),#T$$BFL-4 ;ROOM FOR ONE MORE CHAR. IN BUFFER? BHIS 60$ ;N - JUMP MOVB R2,(R0)+ ;Y - INSERT CHARACTER INC (R1) ;UPDATE BYTE COUNT 40$: CMP (SP)+,(SP)+ ;POP SAVED POSITION AND WRAP-AROUND CONTEXT MOV (SP)+,R2 ;RESTORE CHARACTER ROR (SP)+ ;NEED TO CALL EXPCHR AGAIN WITH THIS CHARACTER? BCS 10$ ;Y - LOOP MOV (SP)+,R3 ;N - RESTORE R3 CALL @(SP)+ ;CALL CALLER BACK BR INSERT ;DO IT AGAIN ; ; CHARACTER EXPANSION DOES NOT FIT IN BUFFER. ; RESTORE CURRENT HORIZONTAL AND VERTICAL POSITION AND STATE VARIABLE. ; 50$: SUB R2,(R1) ;RESTORE BUFFER BYTE COUNT ; ; RESTORE PREVIOUS WRAP AND POSITION CONTEXT. *** NOTE *** MOST BITS OF ; U.TSTA+2 ARE MODIFIED ONLY AT SYSTEM STATE OR DURING CHARACTER ECHOING. ; ECHOING CAN NOT INTERRUPT US HERE BECAUSE INPUT PROCESSING IS DISABLED ; BY S1.DSI. HOWEVER, A FEW BITS ARE MODIFIED DURING INPUT PRIOR TO THE ; S1.DSI CHECK (^O, ^S, TABUF FULL). THE STATE OF THES BITS MUST NOT BE ; DISTURBED WHEN RESTORING WRAP CONTEXT. ; 60$: BIC #S2.BEL!S2.CTO!S2.CTS,(SP) ;CLEAR BITS WE DON'T WANT TO AFFECT BIC #^C,2(R5) ;WIPE OUT BITS WE WANT TO RESET BIS (SP)+,2(R5) ;RESTORE STATUS WORD 2 ASSUME U.TCHP&1,0 ASSUME U.TCVP,U.TCHP+1 MOV (SP)+,U.TCHP-U.TSTA(R5) ;RESTORE CURRENT POSITION ; ; ALLOCATE ANOTHER OUTPUT BUFFER ; MOV -(R1),R2 ;GET POINTER TO NEXT BUFFER BNE 70$ ;THERE IS A FREE BUFFER IN THE LIST - JUMP CALL ALTB ;ALLOCATE ANOTHER BUFFER 70$: MOV R2,R0 ;GET BUFFER ADDRESS (IF WE GOT ONE) MOV (SP)+,R2 ;RESTORE CHARACTER MOV R2,(SP)+ ;POP FLAG WORD (DON'T TOUCH CC-C) MOV (SP)+,R3 ;RESTORE R3 .IF DF T$$RPR BCS 80$ ;FAILED - JUMP .IFF ;T$$RPR BCS CLR16 ;FAILED - CLEAR I.PRM+16 AND ;START OUTPUT .ENDC ;T$$RPR MOV R0,(R1) ;LINK NEW BUFFER TO OLD .SBTTL . SETOBF - INITIALIZE OUTPUT BUFFER HEADER SETOBF: TST (R0)+ ;POINT TO SECOND WORD MOV R0,R1 ;SAVE POINTER IN R1 CLR (R0)+ ;INITIALIZE BYTE COUNT AND POINT ;TO START OF DATA AREA BR INSERT ;START USING NEW BUFFER ; ; FAILED TO ALLOCATE BUFFER ; .IF DF T$$RPR 80$: MOV U.TCO(R4),R3 ;GET REAL PACKET POINTER TST (R3) ;IO.RPR? BEQ CLR16 ;N - START PARTIAL OUTPUT ;AFTER CLEARING I.PRM+16 TST (SP)+ ;POP RETURN ADDRESS ASSUME U.TCHP&1,0 ASSUME U.TCVP,U.TCHP+1 MOV (SP)+,U.TCHP-U.TSTA(R5) ;RESTORE CURRENT POSITION BIC #S2.WRA,2(R5) ;CLEAR WRAP-AROUND CONTEXT MOV #IE.NOD&377,(R3) ;GET STATUS FOR "NO BUFFER AVAILABLE" CLR I.PRM+16(R3) ;USE $IOFIN ;FALL THRU TO "FPORD" TO FINISH REQUEST .ENDC ;T$$RPR .DSABL LSB .PAGE .SBTTL OUTPUT REQUEST COMPLETION .SBTTL . FPORD - OUTPUT REQUEST DONE ; ;+ ; FPORD - OUTPUT REQUEST DONE. ; ; COME HERE WHEN ALL OUTPUT BUFFERS HAVE BEEN OUTPUT. ; TRANSFER MAY OR MAY NOT BE COMPLETED - IF IT IS, ; STATUS IS STORED IN THE LINK WORD OF THE IO PACKET. ; ; THIS ROUTINE IS ENTERED FROM THE FORK DISPATCHER WITH: ; R4 UCBX ADDRESS ; R5 POINTER TO U.TSTA ;- ; FPORD:: MOV U.TCO(R4),R3 ;GET I/O PACKET TST (R3) ;STATUS PRESENT? BNE ORQDON ;Y - JUMP TST U.TTOC(R4) ;ALL DONE? BNE 10$ ;N - MORE TO DO, JUMP ;NOTE - THIS CANNOT HAPPEN WHEN DOING IO.RPR! BIT #S2.CR,2(R5) ;TRAILING CR REQUIRED? BEQ 20$ ;IF EQ, NO...SKIP 10$: MOV R4,R1 ;POINT TO UCBX ADD #U.TFOB,R1 ;POINT TO FIRST OUTPUT BUFFER JMP WRITE1 ;BRANCH AID 20$: INC (R3) ;SET STATUS = IS.SUC .SBTTL . ORQDON - OUTPUT REQUEST HAS FINISHED ; ; OUTPUT DONE. ; ORQDON: CLR U.TCO(R4) ;CLEAR POINTER TO PACKET TO SHOW ;NOT DOING TASK OUTPUT ANY MORE BIC #S1.OBY,(R5) ;SET OUTPUT FREE .IF DF T$$RPR BIT #S5.RPO,U.TST5-U.TSTA(R5) ;WAS THIS PROMPT OF RPR REQUEST? BEQ 20$ ;N - JUMP BIC #S5.RPO,U.TST5-U.TSTA(R5) ;CLEAR PROMPT OUTPUT IN PROGRESS TSTB (R3) ;HAVE AN ERROR ALREADY? BMI 10$ ;Y - JUMP FRKBIT BIS,#FR.GRQ ;TRY ANOTHER PACKET WHEN INPUT ;HAS BEEN STARTED (LINE MAY BE FULL DUPLEX) JMP PPRLB1 ;NOW DO THE READ ;(LEAVE LINK WORD NON-ZERO TO INDICATE ;DOING IO.RPR) 10$: BIC #S1.IBY,(R5) ;SET INPUT FREE CLR U.TFPB(R4) ;CLEAR BUFFER POINTER TST I.PRM+16(R3) ;INTERMEDIATE BUFFERING INITIALIZED? BEQ 15$ ;IF EQ- NO, NO NEED TO DEALLOCATE BUFFER MOV U.TFIB(R4),R2 ;GET INPUT BUFFER POINTER CALL DETB ;DEALLOCATE INPUT BUFFER 15$: .IF DF T$$EIO MOV U.TDIF(R4),R2 ;GET FIRST DEFAULT INPUT BUFFER, IF ANY CALL DELTB ;DEALLOCATE DEFAULT INPUT BUFFERS CLR U.TDIF(R4) ;CLEAR POINTER MOV U.TRTT(R4),R2 ;ANY TERMINATOR TABLE? BEQ 16$ ;BRANCH IF NOT CALL DETB ;DEALLOCATE IT CLR U.TRTT(R4) ;AND CLEAR OUT THE POINTER 16$: .ENDC ;T$$EIO .ENDC ;T$$RPR 20$: .IF DF T$$ACD TST U.ACB-U.TSTA(R5) ;DOES THIS TERMINAL HAVE AN ACD? BEQ 30$ ;N - JUMP MOV #A.OUTP,R0 ;SET OUTPUT COMPLETION ENTRY POINT CALL $SWACD ;CALL ACD .ENDC ;T$$ACD 30$: MOV U.TFOB(R4),R2 ;GET FIRST OUTPUT BUFFER CALL DELTB ;DEALLOCATE ALL BUFFERS MOV I.PRM+4(R3),R1 ;GET NUMBER OF BYTES REQUESTED SUB U.TTOC(R4),R1 ;SUBTRACT U.TTOC ; ; IF A REQUEST IS ABORTED (BY TIME-OUT OR IO.KIL), WE RETURN THE ; NUMBER OF BYTES TRANSFERRED, INCLUDING THE CURRENT (PARTIAL) ; BUFFER. THERE IS NO WAY WE CAN FIND OUT HOW MANY BYTES FROM ; THE TASK'S BUFFER CORRESPOND TO THE NUMBER OF EXPANDED BYTES ; THAT WE SENT FROM THE CURRENT BUFFER. ; ASSUME TF.WIR,200 TSTB I.FCN(R3) ;DOES USER WANT INPUT REDISPLAYED? .IF DF T$$BTW BMI 40$ ;IF MI, YES...DO IT CMPB I.PRI(R3),#251. ;WAS THIS AN IO.WBT? BNE 70$ ;N - JUMP ASSUME S3.FDX,200 TSTB 4(R5) ;FULL DUPLEX LINE? BMI 70$ ;Y - JUMP 40$: .IFF ;T$$BTW BPL 70$ ;IF PL, NO...JUST FINISH THE INPUT REQUEST .ENDC ;T$$BTW ASSUME S1.IBY,200 TSTB (R5) ;INPUT BUSY? BPL 70$ ;N - JUMP ; ; WE JUST FINISHED AN IO.WBT THAT BROKE THROUGH AN INPUT ON A ; NON-FULL-DUPLEX LINE. FAKE A CTRL-R TO REDISPLAY THE CURRENT ; INPUT LINE. ; ; THERE CANNOT BE A FORK REQUEST PENDING FOR INPUT DONE (OR PARTIAL ; INPUT DONE) SINCE INPUT FORK REQUESTS ARE PROCESSED BEFORE OUTPUT ; FORK REQUESTS. ; .IF DF T$$SPL MOVB #CH.CTR,U.TECO-U.TSTA(R5) ;PUT CTRL-R CHAR. IN ECHO BUFFER .IFF ;T$$SPL MOVB #CH.CTR,U.TECB(R4) ;PUT CTRL-R CHAR. IN ECHO BUFFER .ENDC ;T$$SPL FRKBIT BIS,#FR.PFP ;REQUEST POST-FORK PROCESSING .IF DF T$$ESC ; ; IF WE ARE IN THE MIDDLE OF AN ESCAPE SEQUENCE, WE MUST RUB IT OUT ; SINCE THE ESCAPE SEQUENCE AND CTRL-R ROUTINES SHARE U.TISV. ; FURTHERMORE, CTRL-R DOES NOT WORK IF S1.ESC IS SET. ; BIT #S1.ESC,(R5) ;IN ESCAPE SEQUENCE? BEQ 70$ ;N - JUMP MOV R3,-(SP) ;SAVE R3 CALL RUBESC ;Y - RUBOUT THE ESCAPE SEQUENCE MOV (SP)+,R3 ;RESTORE R3 .ENDC ;T$$ESC 70$: CLR I.PRM+12(R3) ;TELL $FINBF NO BUFFERS TO COPY OR DEALLOCATE ; ; FALL THRU TO "DONE" ; .PAGE .SBTTL DONE - GENERAL I/O DONE PROCESSING ; ;+ ; DONE - DO I/O COMPLETION PROCESSING. ; ; INPUT: ; R1 IOSB WORD 2 ; R3 POINTER TO PACKET ; I.LNK = IOSB WORD 1 ; R5 POINTER TO U.TSTA ; I.PRM+16 0 IF $IOFIN TO BE USED, ; NON-0 IF $QUEBF TO BE USED ; ; OUTPUT: ; I/O REQUEST FINISHED. ; ; REGISTERS ALTERED: R0,R1,R2,R3,R4 ;- ; DONE:: FRKBIT BIS,#FR.GRQ ;TIME TO TRY TO GET ANOTHER PACKET MOV (R3),R0 ;GET IOSB WORD 1 TST I.PRM+16(R3) ;USE $QUEBF? BEQ 10$ ;N - JUMP CALLR $QUEBF ;FINISH IO 10$: CALLR $IOFIN ;FINISH IO .END